﻿using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.ComponentModel;
using System;
using System.Collections.Generic;
using System.Data;
using System.Text;
using System.Threading;

namespace Autorun
{
	public partial class PaneCaption : UserControl
	{
		#region "Private Members"
		const int DEFAULT_HEIGHT = 20;
		const string DEFAULT_FONT_NAME = "arial";
		const int DEFAULT_FONT_SIZE = 9;
		const int POS_OFFSET = 4;

		// internal members
		bool active = false;
		bool antiAlias = true;
		bool allowActive = true;

		Color colorActiveText = Color.Black;
		Color colorInactiveText = Color.White;

		Color colorActiveLow = Color.FromArgb(255, 165, 78);
		Color colorActiveHigh = Color.FromArgb(255, 225, 155);
		Color colorInactiveLow = Color.FromArgb(3, 55, 145);
		Color colorInactiveHigh = Color.FromArgb(90, 135, 215);

		// gdi objects
		SolidBrush brushActiveText;
		SolidBrush brushInactiveText;
		LinearGradientBrush brushActive;
		LinearGradientBrush brushInactive;
		StringFormat format;
		#endregion

		#region "Constructors & Destructors"	
		public PaneCaption()
		{
			InitializeComponent();

			// set double buffer styles
			SetStyle(ControlStyles.DoubleBuffer | ControlStyles.UserPaint |
		 ControlStyles.AllPaintingInWmPaint | ControlStyles.ResizeRedraw, true);

			// init the height
			Height = DEFAULT_HEIGHT;

			// format used when drawing the text
			format = new StringFormat();
			format.FormatFlags = StringFormatFlags.NoWrap;
			format.LineAlignment = StringAlignment.Center;
			format.Trimming = StringTrimming.EllipsisCharacter;

			// init the font
			Font = new Font(DEFAULT_FONT_NAME, DEFAULT_FONT_SIZE, FontStyle.Bold);

			// create gdi objects
			ActiveTextColor = colorActiveText;
			InactiveTextColor = colorInactiveText;

			// setting the height above actually does this, but leave
			// in incase change the code (and forget to init the 
			// gradient brushes)
			CreateGradientBrushes();
		}
		#endregion

		#region "Properties"
		[Category("Appearance"),
		Browsable(true),
		DesignerSerializationVisibility(DesignerSerializationVisibility.Visible),
		Description("Text that is displayed in the label.")]
		public override string Text
		{
			get { return base.Text; }
			set
			{
				base.Text = value;
				Invalidate();
			}
		}

		[Description("The active state of the caption, draws the caption with different gradient colors."),
		Category("Appearance"),
		DefaultValue(false)]
		public bool Active
		{
			get { return active; }
			set
			{
				active = value;
				Invalidate();
			}
		}

		[Description("True always uses the inactive state colors, false maintains an active and inactive state."),
		Category("Appearance"),
		DefaultValue(true)]
		public bool AllowActive
		{
			get { return allowActive; }
			set
			{
				allowActive = value;
				Invalidate();
			}
		}

		[Description("If should draw the text as antialiased."),
		Category("Appearance"),
		DefaultValue(true)]
		public bool AntiAlias
		{
			get { return antiAlias; }
			set
			{
				antiAlias = value;
				Invalidate();
			}
		}

		[Description("Color of the text when active."),
		Category("Appearance"),
		DefaultValue(typeof(Color), "Black")]
		public Color ActiveTextColor
		{
			get { return colorActiveText; }
			set
			{
				if (value.Equals(Color.Empty) == true)
					value = Color.Black;
				colorActiveText = value;
				brushActiveText = new SolidBrush(colorActiveText);
				Invalidate();
			}
		}

		[Description("Color of the text when inactive."),
		Category("Appearance"),
		DefaultValue(typeof(Color), "White")]
		public Color InactiveTextColor
		{
			get { return colorInactiveText; }
			set
			{
				if (value.Equals(Color.Empty) == true)
					value = Color.White;
				colorInactiveText = value;
				brushInactiveText = new SolidBrush(colorInactiveText);
				Invalidate();
			}
		}

		[Description("Low color of the active gradient."),
		Category("Appearance"),
		DefaultValue(typeof(Color), "255, 165, 78")]
		public Color ActiveGradientLowColor
		{
			get { return colorActiveLow; }
			set
			{
				if (value.Equals(Color.Empty) == true)
					value = Color.FromArgb(255, 165, 78);
				colorActiveLow = value;
				CreateGradientBrushes();
				Invalidate();
			}
		}

		[Description("High color of the active gradient."),
		Category("Appearance"),
		DefaultValue(typeof(Color), "255, 225, 155")]
		public Color ActiveGradientHighColor
		{
			get { return colorActiveHigh; }
			set
			{
				if (value.Equals(Color.Empty) == true)
					value = Color.FromArgb(255, 225, 155);
				colorActiveHigh = value;
				CreateGradientBrushes();
				Invalidate();
			}
		}

		[Description("Low color of the inactive gradient."),
		Category("Appearance"),
		DefaultValue(typeof(Color), "3, 55, 145")]
		public Color InactiveGradientLowColor
		{
			get { return colorInactiveLow; }
			set
			{
				if (value.Equals(Color.Empty) == true)
					value = Color.FromArgb(3, 55, 145);
				colorInactiveLow = value;
				CreateGradientBrushes();
				Invalidate();
			}
		}

		[Description("High color of the inactive gradient."), Category("Appearance"), DefaultValue(typeof(Color), "90, 135, 215")]
		public Color InactiveGradientHighColor
		{
			get { return colorInactiveHigh; }
			set
			{
				if (value.Equals(Color.Empty) == true)
					value = Color.FromArgb(90, 135, 215);
				colorInactiveHigh = value;
				CreateGradientBrushes();
				Invalidate();
			}
		}

		public SolidBrush TextBrush
		{
			get { return (active == true && allowActive == true) ? brushActiveText : brushInactiveText; }
		}

		public LinearGradientBrush BackBrush
		{
			get { return (active == true && allowActive == true) ? brushActive : brushInactive; }
		}
		#endregion

		#region "Procedures"
		private void DrawCaption(Graphics g)
		{
			RectangleF bounds;

			// background
			g.FillRectangle(BackBrush, DisplayRectangle);

			//caption
			if (antiAlias == true)
				g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;

			//need a rectangle when want to use ellipsis
			bounds = new RectangleF(POS_OFFSET, 0, DisplayRectangle.Width - POS_OFFSET, DisplayRectangle.Height);
			g.DrawString(Text, Font, TextBrush, bounds, format);
		}

		private void CreateGradientBrushes()
		{
			// can only create brushes when have a width and height
			if (Width > 0 && Height > 0)
			{
				if (brushActive != null)
					brushActive.Dispose();
				brushActive = new LinearGradientBrush(DisplayRectangle, colorActiveHigh, colorActiveLow, LinearGradientMode.Vertical);

				if (brushInactive != null)
					brushInactive.Dispose();
				brushInactive = new LinearGradientBrush(DisplayRectangle, colorInactiveHigh, colorInactiveLow, LinearGradientMode.Vertical);
			}
		}
		#endregion

		#region "Event Handlers"
		protected override void OnPaint(PaintEventArgs e)
		{
			DrawCaption(e.Graphics);
			base.OnPaint(e);
		}

		protected override void OnMouseDown(MouseEventArgs e)
		{
			base.OnMouseDown(e);
			if (allowActive == true)
				Focus();
		}

		protected override void OnSizeChanged(System.EventArgs e)
		{
			base.OnSizeChanged(e);
			// create the gradient brushes based on the new size
			CreateGradientBrushes();
		}
		#endregion
	}
}
